package com.swipemaster.record;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import android.app.Activity;
import android.content.Context;
import android.widget.TextView;

import com.swipemaster.R;
import com.swipemaster.common.Const;
import com.swipemaster.common.Global;
import com.swipemaster.game.GameSurface;
import com.swipemaster.levels.levelinfo.LevelInfo;

/** Gives access to records. Don't create an instance of manager, just call its static methods. */
public class RecordsManager
{
	private static Records records;

	private RecordsManager()
	{
	}

	public static void addGamesPlayed()
	{
		final IntegerRecord record = (IntegerRecord) getRecord(RecordId.GAMES_PLAYED);
		record.counter++;
	}

	public static void addStarsForLevel(int levelIndex)
	{
		final LevelInfo levelInfo = getInfo(levelIndex);
		final int oldNumberOfStars = levelInfo.stars;
		final int newNumberOfStars = GameSurface.level.getStars();
		if (newNumberOfStars > oldNumberOfStars)
		{
			levelInfo.stars = newNumberOfStars;

			final IntegerRecord record = (IntegerRecord) getRecord(RecordId.STARS);
			record.counter += newNumberOfStars - oldNumberOfStars;
		}
	}

	public static int getGamesPlayed()
	{
		final IntegerRecord record = (IntegerRecord) getRecord(RecordId.GAMES_PLAYED);
		return record.counter;
	}

	public static LevelInfo getInfo(int levelIndex)
	{
		return getRecords().levelsInfo.getInfo(levelIndex);
	}

	public static int getNumberOfCompletedLevels()
	{
		int result = 0;
		for (int i = 0; i < Const.LEVELS; i++)
		{
			if (getInfo(i).isCompleted)
			{
				result++;
			}
		}
		return result;
	}

	public static Record getRecord(int id)
	{
		return getRecords().getRecord(id);
	}

	public static Record getRecord(RecordId recordId)
	{
		return getRecords().getRecord(recordId);
	}

	/** Get high scores, they will be loaded or created. */
	public static Records getRecords()
	{
		if (records == null)
		{
			createOrLoadRecords();
		}
		return records;
	}

	public static boolean isNewRecordAndUpdate(Record newRecord)
	{
		return getRecords().isNewRecordAndUpdate(newRecord);
	}

	public static void saveRecords()
	{
		getRecords();
		try
		{
			final String filename = Global.app.getString(R.string.high_scores);
			final FileOutputStream fos = Global.app.openFileOutput(filename, Context.MODE_PRIVATE);
			final ObjectOutputStream out = new ObjectOutputStream(fos);
			out.writeObject(records);
			out.close();
		}
		catch (final IOException e)
		{
			e.printStackTrace();
		}
	}

	public static void updateTextViews(Activity activity)
	{
		getRecords();
		TextView textView;

		textView = (TextView) activity.findViewById(R.id.games_played);
		textView.setText(records.getRecord(RecordId.GAMES_PLAYED).toString());

		textView = (TextView) activity.findViewById(R.id.stars);
		textView.setText(records.getRecord(RecordId.STARS).toString() + "/" + (Const.LEVELS * 3));

		textView = (TextView) activity.findViewById(R.id.challenge_record);
		textView.setText(records.getRecord(RecordId.CHALLENGE).toString());

		textView = (TextView) activity.findViewById(R.id.custom_game_record);
		textView.setText(records.getRecord(RecordId.CUSTOM_GAME).toString());
	}

	/** First, try to load records from file. If no such file exists, than create new records. */
	private static void createOrLoadRecords()
	{
		try
		{
			final FileInputStream fis = Global.app.openFileInput(Global.app.getString(R.string.high_scores));
			final ObjectInputStream in = new ObjectInputStream(fis);
			loadRecords(in);
		}
		catch (final IOException e)
		{
			records = new Records();
		}
		catch (final ClassNotFoundException e)
		{
			records = new Records();
		}
	}

	/** Load records from given stream.
	 * @throws IOException
	 * @throws ClassNotFoundException */
	private static void loadRecords(ObjectInputStream in) throws ClassNotFoundException, IOException
	{
		records = (Records) in.readObject();
		in.close();
	}

	public static void unlockLevelsForStars(int stars)
	{
		for (int i = 0; i < Const.LEVELS; i++)
		{
			if (getStarsForLevel(i) <= stars)
			{
				getInfo(i).isLocked = false;
			}
		}
	}

	public static int getStarsForLevel(int levelIndex)
	{
		int stars = 0;
		for (int i = 1, stage = levelIndex / 4; i <= stage; i++)
		{
			if (i > 4)
			{
				stars += 5;
			}
			else
			{
				stars += i;
			}
		}
		return stars;
	}

	public static int getStars()
	{
		return ((IntegerRecord) getRecord(RecordId.STARS)).counter;
	}
}
